home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / (A)TB / (A)TBR.ADF / Utility / FO.c < prev    next >
C/C++ Source or Header  |  1991-10-02  |  27KB  |  1,278 lines

  1. /*
  2. **        FO v1.0 by FBJ
  3. **      
  4. **      (c)Copyright 1991, Campagne Fabien, All Rights Reserved
  5. **
  6. **      Campagne Fabien
  7. **      805, Rue des Gentianes
  8. **      39000 Lons Le saunier
  9. **      FRANCE
  10. **
  11. **    un optimiseur de disk (rapide).
  12. **    FO doit Ωtre linkΘ avec TD.o                                            
  13. **  pour compiler: cc FO "objects:TD.o -gs"                                    
  14. **      
  15. **                                                                          */
  16.  
  17. #include <exec/types.h>
  18. #include <exec/memory.h>
  19. #include <libraries/dos.h>
  20. #include <libraries/dosextens.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include "fbj/Blocks.h"
  24. #include "fbj/ShortBlocks.h"
  25. #include "fbj/TDprotos.h"
  26.  
  27.  
  28. /*#define DEBUG 1
  29. */
  30. #define ON 1L
  31. #define OFF 0L
  32. #define R CMD_READ
  33. #define W CMD_WRITE
  34. #define used 0
  35. #define var Variables
  36. #define BBM VarAdr->BuffBitMap
  37. /*#define BootB VarAdr->BuffTrack*/
  38. #define BT VarAdr->BuffTrack
  39. #define sourceDrive VarAdr->sourcedrive
  40. #define destDrive VarAdr->destdrive
  41. #define dsklist VarAdr->disklist
  42. #define CLI VarAdr->Cli
  43. #define err VarAdr->Err
  44. #define GFree VarAdr->GestFree
  45. #define DFree VarAdr->DataFree
  46. #define FLnog VarAdr->FLnoG
  47. #define drivebusy VarAdr->DriveBusy
  48. #define FORMAT VarAdr->Format
  49. #define CHECK VarAdr->Check
  50.  
  51. extern struct DosLibrary *DOSBase;
  52.  
  53. struct Variables{
  54.     LONG    *BuffBitMap;    /* adr du buffer contenant le bloc BitMap */
  55.     WORD    BitMap;        /* n░ du Block BitMap */
  56.     LONG    *BuffTrack; /* Buffer de track pour le formattage de la destination */
  57.     LONG    *Empty;        /* pointeur sur zone contenant datas pour blocs vides */
  58.     BYTE    sourcedrive;    /* */
  59.     BYTE    destdrive;    /* */
  60.     LONG    TotalBlocks; /* */
  61.     LONG    (*TableMem)[]; /* */
  62.     WORD    EndTMem;    /* indice sur le dernier LONG occupΘ de TableMem */
  63.     WORD    GestFree;    /* dernier bloc de Gestion libre */
  64.     WORD    DataFree;    /* dernier bloc de Data libre */
  65.     LONG    *inCHIP;    /* Buffer 512L en CHIP pour TD */
  66.     struct  DiskList *disklist;    /* */
  67.     BYTE    Cli;    /* if non set, optimize for WB use */
  68.     BYTE    FLnoG;    /* if set, File List will no longuer be considered as Gestion B */
  69.     BYTE    Format; /* if set, the whole disk is formatted */
  70.     BYTE    Check;    /* if set, The Dos Structure of Source is Checked */
  71.     WORD    Err;    /* compteur d' erreur */
  72.     BYTE    DriveBusy[5];
  73. };
  74. struct var *VarAdr;
  75.  
  76. void RendMem(void);
  77. void FreeBusy(void);
  78.  
  79. main(ac,av)
  80. BYTE *av[];
  81. WORD ac;
  82. {
  83. WORD TotalBlocks,i,j=0,Perr=0;
  84. LONG k;
  85. BYTE argn;
  86.     puts("FO v1.0 Fast Optimiser by FBJ.");
  87.     VarAdr=(struct var *)AllocMem(sizeof(struct var),MEMF_CLEAR|MEMF_PUBLIC);
  88.     atexit(RendMem);
  89.  
  90.     WBench(1);                /* ( Par dΘfault ) */
  91.     forFDir(0);
  92.     NoFormat(0);
  93.     Check(0);
  94.  
  95.     if (ac<3 )
  96.     {
  97.         if (*av[1]=='?') {help(); exit(0);}
  98.         else puts("? for help");exit(0);
  99.     }
  100.     if (strnicmp(av[1],"df",2)) {puts("1st arg: source drive"); exit(0);}
  101.     if (strnicmp(av[2],"df",2)) {puts("2nd arg: dest drive"); exit(0);}
  102.     sourceDrive=*(av[1]+2)-48;
  103.     destDrive=  *(av[2]+2)-48;
  104.     if (sourceDrive<0 || sourceDrive>3) {puts("1st arg: source drive"); exit(0);}
  105.     if (destDrive<0 || destDrive>3) {puts("2nd arg: dest drive"); exit(0);}
  106.  
  107.     argn=3;
  108.     while (ac>=argn && *av[argn]=='-')
  109.     {
  110.     switch (*(av[argn]+1)) {
  111.         case 'w' : WBench(1); break;
  112.         case 'W' : WBench(1); break;
  113.         case 'c' : ComLineInt(1); break;
  114.         case 'n' : if ( !strnicmp(av[argn]+1,"nfo",3) ) NoFormat(1); break;
  115.         case 'N' : if ( !strnicmp(av[argn]+1,"nfo",3) ) NoFormat(1); break;
  116.         case 'F' : if ( !strnicmp(av[argn]+1,"FDir",4) ) forFDir(1); break;
  117.         case 'C' : Check(1); break;
  118.         }
  119.     argn++;
  120.     }
  121.     
  122.     puts("Now insert SOURCE disk and RETURN");
  123.     while ( (getchar()) != 10) ;
  124.  
  125.     DiskBUSY(av[2],1);
  126.     atexit(FreeBusy);
  127.     strncpy(drivebusy,av[2],5);
  128.  
  129.     if (!OpenTD(sourceDrive)) {puts("Source drive Not Available"); exit(0);}
  130.     if (!OpenTD(destDrive)) {puts("Dest drive Not Available"); exit(0);}
  131.     atexit(CloseTD);
  132.     VarAdr->inCHIP=(LONG *)AllocMem(512L,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC);
  133.     VarAdr->BuffBitMap=(LONG *)AllocMem(512L,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC);
  134.     Read_WriteB(R,sourceDrive,BBM,880L); /* charge le Root */
  135.     /* on trouve BitMap */
  136.     VarAdr->BitMap=(WORD)((struct RootB *)(VarAdr->BuffBitMap))->BitMapTable[0]; 
  137. #ifdef DEBUG
  138.     printf("n ░ du bloc BitMap :%d\n",VarAdr->BitMap);
  139. #endif
  140.     /* on le charge */
  141.     Read_WriteB(R,sourceDrive,BBM,VarAdr->BitMap);
  142.     /* on rΘserve le buffer de track et on charge le bootBlock o√ il faut */
  143.     BT=(LONG *)AllocMem(11*512L,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC);
  144.     Read_WriteB(R,sourceDrive,BT,0L);
  145.     Read_WriteB(R,sourceDrive,BT+128L,1L);
  146. #ifdef DEBUG
  147.     printf("Adr du Buff de Track : %p\n",BT);
  148. #endif
  149.     VarAdr->Empty=(LONG *)AllocMem(512L,MEMF_CLEAR|MEMF_PUBLIC);
  150.     if (VarAdr->Empty==0) Perr++;
  151.     VarAdr->TotalBlocks=HowBlockUsed(BBM);
  152. #ifdef DEBUG
  153.     printf("Total des Blocks AllouΘs : %d\n",VarAdr->TotalBlocks);
  154. #endif
  155.     VarAdr->TableMem=(APTR)AllocMem(VarAdr->TotalBlocks*4+4,MEMF_CLEAR|MEMF_PUBLIC);
  156. #ifdef DEBUG
  157.     printf("Adr de TableMem : %p\n",&VarAdr->TableMem);
  158. #endif
  159.     j=0;
  160.     for (i=0;i!=VarAdr->TotalBlocks;i++)
  161.     {
  162.     k=AllocMem(512L,MEMF_CLEAR|MEMF_PUBLIC);
  163.     if (k==0) {Perr=103; break;}
  164.     (*VarAdr->TableMem)[j++]=k;
  165.     }
  166.     (*VarAdr->TableMem)[j]=0L;
  167.     VarAdr->EndTMem=j-1;
  168.     
  169.     if (Perr)
  170.     {
  171.         puts("DΘsolΘ, pas assez de mΘmoire pour optimisation rapide");
  172.         exit(0);
  173.     }
  174.     /*    On initialise la strucure DiskList */
  175.     dsklist=(struct SinitB*)AllocMem(sizeof(struct SinitB),MEMF_CLEAR|MEMF_PUBLIC);
  176.     dsklist->dl_Bloc=-9;
  177.     ((struct SinitB*)dsklist)->dl_Type=0;
  178.  
  179.     /*    Avec un bloc initial qui ne sert α rien mais est bien pratique */
  180.  
  181.     LoadBinMem();
  182.     MtrOff(sourceDrive);
  183.     if (CHECK)
  184.     {
  185.         puts("Checking Dos Structure of disk");
  186.         CheckDosStruct();
  187.         if (!err) puts("No Error in Dos Structure");
  188.         else {printf("%d ERRORS on disk !! FO Stopped\n",err); exit(0);}
  189.     }
  190.     MtrOff(sourceDrive);
  191.     puts("Now I optimize ...");
  192.     Optimize();
  193.     BitMap();
  194.     ChangeBlocks();
  195.     puts("Writing result to destination disk");
  196.     MemToDisk();
  197.     puts("Fast Optimization done.");
  198.  
  199.     exit(0);
  200. }
  201.  
  202. void RendMem()
  203. {
  204. LONG    M=1;
  205. WORD    i=0;
  206.     if (VarAdr->BuffBitMap)
  207.     {
  208.         FreeMem(BBM,512L);
  209.         BBM=0L;
  210.     }
  211.     if (VarAdr->BuffTrack)
  212.     {
  213.         FreeMem(BT,11*512L);
  214.         BT=0L;
  215.     }
  216.     if (VarAdr->Empty)
  217.     {
  218.         FreeMem(VarAdr->Empty,512L);
  219.         VarAdr->Empty=0;
  220.     }
  221.     
  222.     i=0;
  223.     while (M)
  224.     {
  225.     M=(*VarAdr->TableMem)[i++];
  226.     if (M) FreeMem(M,512L); else break;
  227.     }
  228.     if (VarAdr->TableMem) FreeMem(VarAdr->TableMem,VarAdr->TotalBlocks*4+4);
  229.     if (dsklist) FreeDiskList();
  230.     if (VarAdr->inCHIP) {FreeMem(VarAdr->inCHIP,512L); VarAdr->inCHIP=0;}
  231.     if (VarAdr) {FreeMem(VarAdr,sizeof(struct var)); VarAdr=0;}
  232.  
  233. }
  234.  
  235. void FreeBusy()
  236. {
  237.     DiskBUSY(drivebusy,0);
  238. }
  239.  
  240. /*    isBlocUsed renvoie 1 si Block libre ou 0 si block occuppΘ 
  241.     il se rΘfΦre au BitMap    */
  242.  
  243. isBlocUsed(Bloc)
  244. WORD    Bloc;
  245. {
  246. LONG    A,B;
  247.     if (Bloc==0 || Bloc==1) return(1); /* Faux car blocks used mais pratique ! */
  248.     A=*(BBM+1+(Bloc-2)/32);
  249.     B=(A>>(((Bloc-2)%32)) & 0x1L);
  250.     return(B);     
  251. }
  252.  
  253. HowBlockUsed(AdrBM)
  254. LONG *AdrBM;
  255. {
  256. WORD i,TotalBlocks=0;
  257.  
  258.     for (i=2;i<=1760;i++)
  259.     {
  260.     TotalBlocks+=(WORD)!(isBlocUsed(i));
  261.     }
  262.     return(TotalBlocks);
  263. }
  264.  
  265. LoadBinMem()
  266. {
  267. LONG    n,m=0;
  268. APTR    buff1,buff2,inCHIP;
  269. struct DiskList *dlist;
  270.  
  271.     inCHIP=VarAdr->inCHIP;
  272.     puts("Reading Source and preparing for Fast Optimising");
  273.     for (n=2;n<1760;n++)
  274.     {
  275.         if (isBlocUsed(n)==used) 
  276.         {
  277.             buff1=(APTR)(Buffer(m++));
  278.             if (TypeOfMem(buff1)&MEMF_CHIP) buff2=buff1;
  279.             else buff2=inCHIP;
  280.             if (Read_WriteB(R,(LONG)sourceDrive,buff2,n)) 
  281.             {
  282.                 puts("Read Error, can' t optimize");
  283.                 exit(0);
  284.             }
  285.             if (buff2==inCHIP) CopyMemQuick(buff2,buff1,512L);
  286. #ifdef DEBUG
  287.     if (!Buffer(m-1))
  288.     {
  289.         puts("ProblΦme avec LoadBinMem !");
  290.         exit(0);
  291.     }
  292. #endif
  293.         Organising(buff1,dlist,n);
  294.         }        
  295.         if ((n%22)==0)
  296.         {
  297.             printf("CYL %d",n/22);
  298.             putchar(13);
  299.             fflush(stdout);
  300.         }
  301.         
  302.     }
  303.     
  304. }
  305.  
  306. /*    Cherche et renvoie l' adresse o√ ranger le bloc */
  307. Buffer(m)
  308. LONG m;
  309. {
  310.     return((*VarAdr->TableMem)[m]);
  311. }
  312.  
  313. Organising(buff1,dlist,n)
  314. LONG    *buff1;
  315. LONG    n;
  316. struct DiskList *dlist;
  317.  
  318. {
  319.     switch (*buff1)
  320.     {
  321.         case 2L :
  322.         {
  323.             switch (*(buff1+127))
  324.             {
  325.  
  326.                 case 1L: /* RootBlock */
  327.                 {
  328.                 /*    printf("Type : RootB , bloc #%d\n",n);*/
  329.                     dlist=(struct DiskList *)Preparing(sizeof(struct SRootB),dsklist);
  330.                     dlist->dl_NextB=0;
  331.                     dlist->dl_Bloc=n;
  332.                     dlist->dl_Bloc2=n;
  333.                     dlist->dl_Data=0;
  334.                     dlist->dl_Type=3;
  335.                     dlist->dl_types.dl_type3.reserved1=0;
  336.                     dlist->dl_AdrB=buff1;
  337.                     break;
  338.                 }
  339.  
  340.                 case -3L: /* File Header Block */
  341.                 {
  342.                 /*    printf("Type : File HeaderB , bloc #%d\n",n);*/
  343.                     dlist=(struct DiskList *)Preparing(sizeof(struct SFileHderB),dsklist);
  344.                     dlist->dl_NextB=0;
  345.                     dlist->dl_Bloc=n;
  346.                     dlist->dl_Bloc2=0;
  347.                     dlist->dl_Type=-1;
  348.                     dlist->dl_types.dl_type1.dl_Parent=((struct FileHeaderB*)buff1)->ParentDir;
  349.                     dlist->dl_types.dl_type1.dl_NextHash=((struct FileHeaderB*)buff1)->NextHash;
  350.                     dlist->dl_types.dl_type1.dl_Extension=((struct FileHeaderB*)buff1)->Extension;
  351.                     dlist->dl_AdrB=buff1;
  352.                     dlist->dl_Data=isinfo(buff1);
  353.                     break;
  354.                 }
  355.  
  356.                 case 2L: /* User Directory Block */
  357.                 {
  358.                 /*    printf("Type : User DirB , bloc #%d\n",n);*/
  359.                     dlist=(struct DiskList *)Preparing(sizeof(struct SUserDirB),dsklist);
  360.                     dlist->dl_NextB=0;
  361.                     dlist->dl_Bloc=n;
  362.                     dlist->dl_Bloc2=0;
  363.                     dlist->dl_Type=4;
  364.                     dlist->dl_types.dl_type4.dl_Parent=((struct UserDirB*)buff1)->ParentDir;
  365.                     dlist->dl_types.dl_type4.dl_NextHash=((struct UserDirB*)buff1)->NextHash;
  366.                     dlist->dl_AdrB=buff1;
  367.                     dlist->dl_Data=isinfo(buff1);
  368.                     break;
  369.                 }
  370.  
  371.                 default :
  372.                 {
  373.                     printf("Type : UnknownB1 , bloc #%d\n",n); 
  374.                     dlist=(struct DiskList *)Preparing(sizeof(struct SUnknownB),dsklist);
  375.                     dlist->dl_NextB=0;
  376.                     dlist->dl_Bloc=n;
  377.                     dlist->dl_Bloc2=n;
  378.                     dlist->dl_Data=0;
  379.                     dlist->dl_Type=-2;
  380.                     dlist->dl_AdrB=buff1; 
  381.                     break;
  382.                 }
  383.             }
  384.             break;
  385.         }
  386.  
  387.         case 16L: if (*(buff1+127)==-3) /* FileList Block */
  388.         {
  389.         /*    printf("Type : File ListB , bloc #%d\n",n);*/
  390.             dlist=(struct DiskList *)Preparing(sizeof(struct SFileListB),dsklist);
  391.             dlist->dl_NextB=0;
  392.             dlist->dl_Bloc=n;
  393.             dlist->dl_Bloc2=0;
  394.             dlist->dl_Data=0;
  395.             dlist->dl_Type=13;
  396.             dlist->dl_types.dl_type13.dl_FileHeader=((struct FileListB*)buff1)->ParentFH;
  397.             dlist->dl_types.dl_type13.dl_Extension=((struct FileListB*)buff1)->Extension;
  398.             dlist->dl_AdrB=buff1;
  399.             break;
  400.         }
  401.  
  402.         case 8L: /* Data Block */
  403.         {
  404. /*        printf("Type : DataB , bloc #%d\n",n);*/
  405.         dlist=(struct DiskList *)Preparing(sizeof(struct SDataB),dsklist);
  406.         dlist->dl_NextB=0;
  407.         dlist->dl_Bloc=n;
  408.         dlist->dl_Bloc2=0;
  409.         dlist->dl_Data=0;
  410.         dlist->dl_Type=8;
  411.         dlist->dl_types.dl_type8.dl_FileHeader=((struct DataB*)buff1)->HeaderKey;
  412.         dlist->dl_types.dl_type8.dl_NextData=((struct DataB*)buff1)->NextDataBlock;
  413.         dlist->dl_AdrB=buff1;
  414.         break;
  415.         }
  416.     
  417.         default :
  418.         {
  419. /*            printf("Type : UnknownB2 , bloc #%d\n",n); *//* Par ex le B BitMap */
  420.             if (n==VarAdr->BitMap) break;
  421.             dlist=(struct DiskList *)Preparing(sizeof(struct SUnknownB),dsklist);
  422.             dlist->dl_NextB=0;
  423.             dlist->dl_Bloc=n;
  424.             dlist->dl_Bloc2=n;
  425.             dlist->dl_Data=0;
  426.             dlist->dl_Type=-2;
  427.             dlist->dl_AdrB=buff1;
  428.             break;
  429.         }
  430.     }
  431. }
  432.  
  433. Preparing(structsize,adr)
  434. LONG structsize;
  435. struct DiskList *adr;
  436.  
  437. {
  438. static struct DiskList *Sadr=0;
  439.  
  440.     if (Sadr==0) Sadr=adr; else adr=Sadr;
  441.     if (adr->dl_NextB==0)
  442.     {
  443.         adr->dl_NextB=(struct DiskList *)AllocMem(structsize,MEMF_PUBLIC);
  444.         if (adr->dl_NextB==0)
  445.         {
  446.             puts("Pas de mem pour Preparing()");
  447.             exit(0);
  448.         }
  449.         Sadr=adr->dl_NextB;
  450.         return(adr->dl_NextB);
  451.     }
  452.     else return(Preparing(structsize,adr->dl_NextB));
  453. }
  454.  
  455. FreeDiskList()
  456. {
  457. struct DiskList *dlist;
  458. LONG    length=0;
  459. APTR    tmp;
  460.  
  461.     dlist=dsklist;
  462.     do
  463.     {
  464.         length=Length(dlist);
  465.         tmp=dlist->dl_NextB;
  466.         if (dlist && length) FreeMem(dlist,length); 
  467.         dlist=tmp;
  468.     }
  469.     while (dlist->dl_NextB!=0);
  470.     FreeMem(dlist,Length(dlist));    
  471.     dsklist=0;
  472.  
  473. }
  474.  
  475. Length(dlist)
  476. struct DiskList *dlist;
  477. {
  478. LONG length;
  479.     switch (dlist->dl_Type)
  480.     {
  481.         case -2L: length=sizeof(struct SUnknownB); break;
  482.         case 13L: length=sizeof(struct SFileListB); break;
  483.         case  8L: length=sizeof(struct SDataB); break;
  484.         case  4L: length=sizeof(struct SUserDirB); break;
  485.         case  3L: length=sizeof(struct SRootB); break;
  486.         case -1L: length=sizeof(struct SFileHderB); break;
  487.         case  0L: length=sizeof(struct SinitB); break;
  488.         default : length=0; puts("err in FreeDiskList"); break;
  489.     }
  490.     return(length);    
  491. }
  492.  
  493. CheckDosStruct()
  494. {
  495. struct DiskList *dlist;
  496. WORD n;
  497. struct RootB *adr;
  498.  
  499.     dlist=(APTR)whereB(880);
  500.     if (dlist==0) NotSet(880);
  501.     else
  502.  
  503.  
  504.     {    adr=(struct RootB *)dlist->dl_AdrB;
  505.         for (n=0;n<72;n++) /* 72 compris puisque n++ */
  506.         {
  507.             explore(adr->HashTable[n],880);
  508.         }
  509.     }
  510. }
  511.  
  512. /*    explore: suit une chaine de Hash α partir du bloc header en paramΦtre */
  513.  
  514. explore(bloc,parent)
  515. WORD bloc;
  516. WORD parent;
  517. {
  518. struct DiskList *dlist; 
  519. WORD n,nextbloc;
  520. struct UserDirB *adr;
  521.  
  522.     if (bloc==0) return(0);
  523.     /*printf("dans explore bloc: %d, parent: %d\n",bloc,parent);*/
  524.     dlist=VarAdr->disklist;
  525.     while (dlist->dl_Bloc!=bloc && dlist!=0)        dlist=dlist->dl_NextB;
  526.  
  527.     if (dlist==0) NotSet(bloc,parent);
  528.     else
  529.  
  530.     if (dlist->dl_Type!=-1 && dlist->dl_Type!=4)
  531.     {
  532.         printf ("ERR : Block #%d SHOULD BE Header or UserDir block\n",bloc);
  533.         err++;
  534.     }
  535.  
  536.     if (dlist->dl_types.dl_type4.dl_Parent!=parent)
  537.     {
  538.         printf("ERR : Link Error between block #%d and #%d\n",bloc,parent);
  539.         err++;
  540.     }
  541.  
  542.     if (dlist->dl_Type==-1) CheckHeader(dlist);
  543.     if (dlist->dl_Type==4) 
  544.     {
  545.         adr=(struct UserDirB *)dlist->dl_AdrB;
  546.         for (n=0;n<72;n++)
  547.         {
  548.             explore(adr->HashTable[n],bloc);    
  549.         }
  550.     }
  551.  
  552.     if (nextbloc=dlist->dl_types.dl_type1.dl_NextHash==0) return(0);
  553.     else explore(nextbloc,parent);
  554. }
  555.  
  556. CheckHeader(dlist)
  557. struct DiskList *dlist;
  558. {
  559. WORD bloc,n;
  560. struct FileHeaderB *adr;
  561. BYTE errfile=0;
  562.  
  563.     bloc=dlist->dl_Bloc;
  564.     /*printf("dans CheckHeader bloc: %d\n",bloc);*/
  565.     adr=dlist->dl_AdrB;
  566.  
  567.     for (n=0;n<72;n++)
  568.     {
  569.         errfile+=CheckLink(adr->DataTable[n],bloc);
  570.     }
  571.     if (adr->Extension) CheckFList(adr->Extension,bloc);
  572.  
  573.  
  574.     if (errfile) badFile(adr->FileName);
  575.     return(0);
  576. }
  577. CheckFList(bloc,fhb)
  578. WORD bloc,fhb;
  579. {
  580. struct SFileListB *dlistFL;
  581. struct FileListB  *adr;
  582. BYTE   errfile=0;
  583. WORD   n;
  584.  
  585.     dlistFL=(APTR)whereB(bloc);
  586. /*    printf("dans CheckFList bloc: %d, pour FHB: %d\n",bloc,fhb);*/
  587.     if (dlistFL==0) NotSet(bloc,fhb);
  588.     else{
  589.     if (dlistFL->dl_Type!=13)
  590.     {
  591.         printf ("ERR : Block #%d SHOULD BE FileList block\n",bloc);
  592.         err++;
  593.         errfile++;
  594.     }
  595.     else
  596.     {
  597.         adr=(struct FileListB *)dlistFL->dl_AdrB;
  598.         if (adr->ParentFH!=fhb)
  599.         {
  600.             printf("ERR : Link Error between block #%d and #%d\n",bloc,fhb);
  601.             err++;
  602.         }
  603.         for (n=0;n<72;n++)
  604.         {
  605.             errfile+=CheckLink(adr->DataTable[n],fhb);
  606.         }
  607.     }
  608.     if (adr->Extension) errfile+=CheckFList(adr->Extension,fhb);
  609.     }
  610.     return(errfile);
  611. }
  612.  
  613. CheckLink(dataB,fhB)
  614. WORD dataB,fhB;
  615. {
  616. struct SDataB *dlist;
  617. BYTE errdata=0;
  618.  
  619.     if (dataB==0) return(0);
  620. /*    printf("dans CheckLink data : %d, fh : %d\n",dataB,fhB);*/
  621.     dlist=(struct SDataB *)VarAdr->disklist;
  622.     while (dlist->dl_Bloc!=dataB && dlist!=0)        dlist=dlist->dl_NextB;
  623.  
  624.     if (dlist==0) NotSet(dataB,fhB);
  625.     else
  626.  
  627.     if (dlist->dl_Type!=8)
  628.     {
  629.         printf ("ERR : Block #%d SHOULD BE data block (pointed by FHB #%d)\n",dataB,fhB);
  630.         err++;
  631.         errdata=1;
  632.     }
  633.     else
  634.     if (dlist->dl_type8.dl_FileHeader!=fhB)
  635.     {
  636.         printf("ERR : Link Error between block #%d and #%d\n",fhB,dataB);
  637.         err++;
  638.         errdata=1;
  639.     }
  640.     return(errdata);
  641. }
  642.  
  643. badFile(adrName)
  644. BYTE *adrName;
  645. {
  646. BYTE length;
  647. BYTE buff[30];
  648.  
  649.     length=*adrName;
  650.     adrName++;
  651.     strncpy(buff,adrName,length);
  652.     buff[length]=0;
  653.     printf("File %s contains errors\n",buff);
  654. }
  655.  
  656. NotSet(bloc,where)
  657. WORD bloc,where;
  658. {
  659.     printf("Block #%d Not Found ! (not unset in BitMap), in %p\n",bloc,where);
  660.     err++;
  661. }
  662.  
  663. whereB(bloc)
  664. WORD bloc;
  665. {
  666. struct DiskList *dlist;
  667.  
  668.     dlist=VarAdr->disklist;
  669.     while (dlist->dl_Bloc!=bloc && dlist!=0) dlist=dlist->dl_NextB;
  670.     return(dlist);
  671. }
  672. isinfo(buff)
  673. BYTE *buff;
  674. {
  675. BYTE name[30],length,n;
  676.  
  677.  
  678.     length=buff[108*4];
  679.     strncpy(name,buff+108*4+1,length);
  680.     name[length]=0;
  681.     for (n=0; n<length && name[n] != '.';++n);
  682.     if (stricmp(name+n,".info")==0)
  683.     return(1);
  684.     else return(0);
  685. }
  686.  
  687. Optimize()
  688. {
  689. WORD UDB[100];
  690. WORD i=1;
  691.  
  692.     UDB[0]=880;
  693.     UDB[1]=0;
  694.     /*printf("UDB[0] : %d\n",UDB[0]);*/
  695.     while (UDB[0])
  696.     {if (!arrange(UDB,&i)) break;} 
  697.  
  698. }
  699.  
  700. arrange(UDB,i)
  701. WORD UDB[],*i;
  702. {
  703. static WORD gfree=882,dfree=2;
  704. struct SUserDirB *udbf,*udbp,*fhB;
  705. struct UserDirB  *adrf;
  706. struct UserDirB  *adrp;
  707. /*struct DiskList     *hdb;*/
  708. struct FileHeaderB *adrh;
  709. WORD   UDBP,n,bloc,parent;
  710.  
  711. /*    printf("in arrange() UDB[0] : %d, i : %d\n",UDB[0],*i);*/
  712.     udbf=(APTR)whereB(UDB[0]);
  713.     if (udbf==0) {NotSet(UDB[0],0); return(0);}
  714.  
  715.     for (n=0;n<*i;n++) UDB[n]=UDB[n+1];    /* On s' occuppe de UDB[0] donc on le retire de la liste */
  716.     UDB[*i]=0;
  717.     (*i)--;
  718.  
  719.     UDBP=udbf->dl_type4.dl_Parent;
  720.  
  721.     if (UDBP)    /* null si Root */
  722.     {
  723.         udbp=(APTR)whereB(UDBP);
  724.         if (udbp==0) {NotSet(UDBP,1); return(0);}
  725.     }
  726.  
  727.     adrf=udbf->dl_AdrB;
  728.     /*printf("adrf : %p\n",adrf);*/
  729.  
  730.     if (UDBP)    /* Cas du User Dir B */
  731.     {
  732.         adrp=udbp->dl_AdrB;
  733.         parent=adrf->ParentDir=udbp->dl_Bloc2;    /* Les Parents sont tjs dΘplacΘs avt */
  734.     }
  735.  
  736.     for (n=71;n!=-1;n--)
  737.     {
  738.     
  739.         bloc=adrf->HashTable[n];
  740.         if (bloc)
  741.         {
  742.             adrf->HashTable[n]=gfree;
  743.             do
  744.             {
  745.                 fhB=(APTR)whereB(bloc);
  746.                 if (fhB==0) {NotSet(bloc,2); break;}
  747.  
  748.                 if (fhB->dl_Type==-1)
  749.                 {
  750.                     gfree=MoveHderB(bloc,gfree,&dfree,UDB,i);
  751.                 }
  752.                 else
  753.                 if (fhB->dl_Type==4)
  754.                 {
  755.                     gfree=MoveUserDirB(bloc,gfree,parent);
  756.                     UDB[(*i)++]=bloc;
  757.                     UDB[*i]=0;
  758.                 }
  759.  
  760.                 adrh=(struct FileHeaderB *)fhB->dl_AdrB;
  761.                 bloc=adrh->NextHash;
  762.                 adrh->NextHash= (bloc ? gfree : 0);
  763.                 /*printf("adrh: %p,bloc: %d\n",adrh,bloc);*/
  764.             }
  765.             while (bloc);
  766.         }
  767.     }
  768.     /*printf("gfree: %d dfree: %d\n",gfree,dfree);*/
  769.     GFree=gfree;
  770.     DFree=dfree;
  771.     return(1);
  772. }
  773.  
  774.  
  775.  
  776.  
  777. Inc(datafree)
  778. WORD *datafree;
  779. {
  780. #ifdef DEBUG
  781. /*    printf("in Inc() datafree: %d\n",*datafree);*/
  782. #endif
  783.     if (*datafree<879) (*datafree)++; /* Ainsi 879 est donnΘ mais pas 880 */
  784.     else
  785.     {
  786.         if (*datafree==879) *datafree=1759;
  787.         else (*datafree)--;
  788.     }
  789.     return(*datafree);
  790. }
  791.  
  792. Nextdfree(datafree)
  793. WORD *datafree;
  794. {
  795.     if (*datafree<879) return(*datafree+1); 
  796.     else
  797.     {
  798.         if ((*datafree+1)==880) return(1759);
  799.         else return(*datafree-1);
  800.     }
  801. }
  802.  
  803. /*    MoveHderB dΘplace le Header spΘcifiΘ du bloc lB au bloc nB.
  804.     nB: nouveau n░ de bloc.
  805.     oB: ancien  n░ de bloc.
  806. */
  807.  
  808. MoveHderB(oB,nB,datafree,UDB,i)
  809. WORD nB,oB,*datafree;
  810. WORD UDB[],*i;
  811. {
  812. struct SFileHderB *dlistB,*fhB;
  813. struct FileHeaderB *adr;
  814. struct DiskList     *hdb;
  815. struct FileHeaderB *adrh;
  816. WORD   n,ret,ext,bloc,*nflB;
  817. WORD   gfree;
  818. LONG   AdrD;
  819. BYTE   first;
  820. #ifdef DEBUG
  821.     printf("in MoveHderB() oB: %d, nB: %d,datafree: %d\n",oB,nB,*datafree);
  822. #endif
  823.     dlistB=(APTR)whereB(oB);
  824.     if (dlistB==0) NotSet(oB,4);
  825.     else
  826.     {
  827.         if (dlistB->dl_Type!=-1) return(0);
  828.         adr=(struct FileHeaderB *)dlistB->dl_AdrB;
  829.             /* On change le HeaderKey du bloc */
  830.         adr->HeaderKey=nB;
  831.         dlistB->dl_Bloc2=nB;
  832.  
  833.             /* On change tous les DatasB en consΘquence */
  834.         gfree=nB+1;
  835.         first=1;
  836.  
  837.         for (n=71;n!=-1;n--)
  838.         {    
  839.             if (adr->DataTable[n])
  840.             {
  841.                 if ( (dlistB->dl_Data==1) && (CLI==0) ) /* bloc de data ds gestion */
  842.                 {
  843.                     AdrD=ModifyDataHder(adr->DataTable[n],nB,gfree,adr);
  844.                     adr->DataTable[n]=gfree;
  845.                     if (first) {adr->FirstDataB=gfree; first=0;}
  846.  
  847.                     gfree++;
  848.                     if (n) ModifyDataNext(AdrD,gfree);
  849.                     else ModifyDataNext(AdrD,gfree+1);
  850.                 }
  851.                 else
  852.                 {
  853.                     AdrD=ModifyDataHder(adr->DataTable[n],nB,*datafree,adr);
  854.                     adr->DataTable[n]=*datafree;
  855.                     if (first) {adr->FirstDataB=*datafree; first=0;}
  856.  
  857.                     Inc(datafree);
  858.                     if (n) ModifyDataNext(AdrD,*datafree);
  859.                     else
  860.                     {
  861.                         if (FLnog) ModifyDataNext(AdrD,Nextdfree(datafree));
  862.                         else ModifyDataNext(AdrD,*datafree);
  863.                     }
  864.                 }
  865.  
  866.             }
  867.         }
  868.  
  869.         if (adr->Extension) 
  870.         {
  871.             if (FLnog) 
  872.             {
  873.                 nflB=datafree;
  874.                 ext=*datafree;
  875.             }    
  876.             else
  877.             {
  878.                 nflB=&gfree;
  879.                 ext=gfree;
  880.             }
  881.             if (CLI)    /* pas de .info dans les blocs de gestion */
  882.             {
  883.                 ModifyFList(adr->Extension,nB,nflB,datafree,0);
  884.             }
  885.             else
  886.             if (dlistB->dl_Data==1) /* si .info alors ds les blocs de gestion */
  887.             {
  888.                 ModifyFList(adr->Extension,nB,nflB,&gfree,1);
  889.             }
  890.             else
  891.             {
  892.                 ModifyFList(adr->Extension,nB,nflB,datafree,0);
  893.             }
  894.             adr->Extension=ext;
  895.         }
  896.  
  897.  
  898.     }
  899.     return(gfree);
  900. }
  901.  
  902. ModifyDataHder(bloc,nfhB,ndataB,adrfh)
  903. WORD bloc,nfhB,ndataB;
  904. LONG adrfh;
  905. {
  906. struct SDataB *dlistD;
  907. struct DataB  *adr;
  908.  
  909. #ifdef DEBUG
  910.     printf("in MofifyDataHder() bloc: %d, nfhB : %d, ndataB: %d\n",bloc,nfhB,ndataB);
  911. #endif
  912.     dlistD=(APTR)whereB(bloc);
  913.     if (dlistD==0) {NotSet(bloc,adrfh); exit(0);}
  914.     else
  915.     dlistD->dl_Bloc2=ndataB;
  916.     dlistD->dl_type8.dl_FileHeader=nfhB;
  917.     adr=dlistD->dl_AdrB;
  918.     adr->HeaderKey=nfhB;
  919.     return(adr);
  920. }
  921.  
  922. ModifyDataNext(adr,ndataNext)
  923. WORD ndataNext;
  924. struct DataB *adr;
  925. {
  926.     if (adr->NextDataBlock)    adr->NextDataBlock=ndataNext;
  927.  
  928. }
  929.  
  930. /* Renvoie n░ du prochain bloc libre */
  931.  
  932. ModifyFList(bloc,nfhB,nflB,datafree,data)
  933. WORD bloc,nfhB,*nflB,*datafree,data;
  934. {
  935. struct SFileListB *dlistFL;
  936. struct FileListB  *adr;
  937. LONG   *AdrD;
  938. WORD   n,ret=0,ext;
  939. BYTE   first;
  940. #ifdef DEBUG
  941.     printf("in MofifyFList() bloc: %d, nfhB : %d, nflB: %d,datafree: %d\n",bloc,nfhB,*nflB,(*datafree)+1);
  942. #endif
  943.     dlistFL=(APTR)whereB(bloc);
  944.     if (dlistFL==0) NotSet(bloc,5);
  945.     else
  946.     {
  947.         /*printf(" Type du bloc: %d\n",dlistFL->dl_Type);*/
  948.         dlistFL->dl_type13.dl_FileHeader=nfhB;
  949.         dlistFL->dl_Bloc2=*nflB;
  950.         adr=(struct FileListB *)dlistFL->dl_AdrB;
  951.         adr->ParentFH=nfhB;
  952.         adr->HeaderKey=*nflB;
  953.         if (FLnog) Inc(nflB); else (*nflB)++;
  954.         
  955.         first=1;
  956.         for (n=71;n!=-1;n--)
  957.         {
  958.             if(adr->DataTable[n])
  959.             {
  960.                 AdrD=(APTR)ModifyDataHder(adr->DataTable[n],nfhB,*datafree,bloc);
  961.                 adr->DataTable[n]=*datafree;
  962.                 if (first) {adr->FirstDataB=*datafree; first=0;}
  963.  
  964.                 if (data==0) Inc(datafree); else (*datafree)++;
  965.  
  966.                 if (n)
  967.                 {
  968.                     if (data==0) ModifyDataNext(AdrD,*datafree);
  969.                     else ModifyDataNext(AdrD,*datafree+1);
  970.                 }
  971.                 else
  972.                 {
  973.                     if (FLnog) ModifyDataNext(AdrD,Nextdfree(datafree));
  974.                     else ModifyDataNext(AdrD,*datafree);
  975.                 }
  976.             }
  977.         }
  978.  
  979.         ext=*nflB;
  980.         if (adr->Extension) 
  981.         {
  982.             ret+=ModifyFList(adr->Extension,nfhB,nflB,datafree,data);
  983.             adr->Extension=ext;
  984.             return(++ret);
  985.         }
  986.  
  987.         return(ext);
  988.     }
  989. }
  990.  
  991. MoveUserDirB(oB,nB,parent)
  992. WORD oB,nB,parent;
  993. {
  994. struct SUserDirB *dlist;
  995. struct UserDirB *adr;
  996. WORD n;
  997.  
  998. #ifdef DEBUG
  999.     printf("in MoveUserDir() oB: %d, nB: %d, parent: %d\n",oB,nB,parent);
  1000. #endif
  1001.     dlist=(APTR)whereB(oB);
  1002.     if (dlist==0) NotSet(oB,6);
  1003.     else
  1004.     {    
  1005.         if (dlist->dl_Type==4)
  1006.         {
  1007.  
  1008.             adr=dlist->dl_AdrB;
  1009.             dlist->dl_Bloc2=nB;
  1010.             adr->HeaderKey=nB;
  1011.             for (n=71;n!=-1;n--)
  1012.             {
  1013.                 if (adr->HashTable[n])
  1014.                 {
  1015.                     MoveHashFils(adr->HashTable[n],nB);
  1016.                 }
  1017.             }
  1018.         return(nB+1);
  1019.         } else puts("err in MoveUserDirB");
  1020.     }
  1021. }
  1022.  
  1023. MoveHashFils(bloc,parent)
  1024. WORD bloc,parent;
  1025. {
  1026. struct DiskList *dlist;
  1027. struct  FileHeaderB *adr;
  1028.  
  1029. #ifdef DEBUG
  1030.     printf("in MoveHashFils() bloc: %d, parent: %d\n",bloc,parent);
  1031. #endif
  1032.     dlist=(APTR)whereB(bloc);
  1033.     if (dlist==0) {NotSet(bloc,7); return(0);}
  1034.  
  1035.     if (dlist->dl_Type==-1) adr=dlist->dl_AdrB;
  1036.     if (dlist->dl_Type==4) adr=dlist->dl_AdrB;
  1037.  
  1038.     dlist->dl_types.dl_type4.dl_Parent=parent;
  1039.     adr->ParentDir=parent;
  1040. }
  1041.  
  1042. ChangeBlocks()
  1043. {
  1044. struct DiskList *dlist;
  1045.  
  1046.     dlist=(struct DiskList *)VarAdr->disklist;
  1047.  
  1048.     while (dlist) 
  1049.     {
  1050.         dlist->dl_Bloc=dlist->dl_Bloc2;
  1051.         dlist=dlist->dl_NextB;
  1052.     }
  1053.  
  1054. }
  1055.  
  1056. MemToDisk()
  1057. {
  1058. WORD n,bitmap;
  1059. LONG offset,*adrB,*empty,ddrive,A;
  1060. BYTE *BuffT,write,length;
  1061. WORD c,Form;
  1062. struct DiskList *dlist=0;
  1063. struct RootNode *RN;
  1064. struct RootB *adr;
  1065.  
  1066.     if (sourceDrive==destDrive) {puts("Now insert dest disk and RETURN");
  1067.     while ( (c=getchar()) != 10) ;}
  1068.  
  1069.     MtrOn(destDrive);
  1070.     MtrOff(destDrive);
  1071.     if (isInserted(destDrive)) {puts("YOU MUST insert DESTINATION disk and RETURN");
  1072.     while ( (c=getchar()) != 10) ;
  1073.     while (isInserted(destDrive)) fflush(stdout); }
  1074.  
  1075.     if (isProtected(destDrive)) {puts("UnProtect DESTINATION disk and press RETURN");
  1076.     while ( (c=getchar()) != 10) ;
  1077.     while (isProtected(destDrive)) fflush(stdout);}
  1078.     
  1079.  
  1080.     offset=2*512L;    /* Le boot Block est dΘja dans le Buffer de Track */
  1081.     BuffT=BT;
  1082.     /*    On met α jour la date de derniΦre modif de la disquette */
  1083.     dlist=(APTR)whereB(880);
  1084.     if (dlist==0) NotSet(880,8);
  1085.     adr=dlist->dl_AdrB;
  1086.     RN=(struct RootNode *)(DOSBase->dl_Root);
  1087.     adr->Mday=RN->rn_Time.ds_Days;
  1088.     adr->Mmin=RN->rn_Time.ds_Minute;
  1089.     adr->Mtick=RN->rn_Time.ds_Tick;
  1090.  
  1091.     length=adr->DiskName[0];
  1092.     adr->DiskName[0]=length+1;
  1093.     adr->DiskName[length+1]='.';
  1094.  
  1095.  
  1096.     bitmap=VarAdr->BitMap;
  1097.     empty=VarAdr->Empty;
  1098.     ddrive=destDrive;
  1099.     A=('F'<<24|'B'<<16|'J'<<8|'.');
  1100.  
  1101.     for (n=0;n<128;n++)
  1102.     {
  1103.         empty[n]=A;
  1104.     }
  1105.  
  1106.     /*printf("buffer a l' adresse %p\n",empty);*/
  1107.     putchar(13);
  1108.  
  1109.     Form=FORMAT;
  1110.     /*printf("Form : %d, VarAdr->Format: %ld\n",Form,VarAdr->Format);*/
  1111.     write=Form;
  1112.     for (n=2;n<1761;n++)
  1113.     {
  1114.         if (offset==11*512) 
  1115.         {
  1116.             /*printf("(n-12): %d\n",(n-11));    */
  1117.             if (write)    CMDonD(ddrive,TD_FORMAT,0,11*512L,BuffT,(n-11)*512L);
  1118.             offset=0L;
  1119.             if (!Form) write=0;
  1120.         }
  1121.         if (( (n-22) % 22 )==0)
  1122.         {
  1123.             printf("CYL n░: %d",n/22);
  1124.             putchar(13);
  1125.             fflush(stdout);
  1126.         }
  1127.         if (n==881) {adrB=BBM; write=1;}
  1128.         else 
  1129.         {
  1130.             dlist=(APTR)whereB(n);
  1131.             if (dlist==0) adrB=empty;
  1132.             else 
  1133.             {
  1134.                 adrB=dlist->dl_AdrB;
  1135.                 BuildCheckSum(adrB);
  1136.                 write=1;
  1137.             }
  1138.         }    
  1139.         CopyMemQuick(adrB,BuffT+offset,512L);
  1140.         offset+=512L;
  1141.     }
  1142.  
  1143. BuildCheckSum(Buffer)
  1144. ULONG *Buffer;
  1145. {
  1146. ULONG B;
  1147. WORD    n;
  1148.     
  1149.     Buffer[5]=0;
  1150.     n=0;
  1151.     B=0;
  1152.     while (n<=127)
  1153.     {
  1154.         B+=Buffer[n]; 
  1155.         n++;
  1156.     }
  1157.     Buffer[5]=-B;
  1158. }
  1159.  
  1160. BitMap()
  1161. {
  1162. struct DiskList *dlist;
  1163. struct RootB *adr;
  1164. WORD     n;
  1165. LONG    *buffbm,SBM=0;
  1166.  
  1167.     buffbm=BBM;
  1168.     dlist=(APTR)whereB(880);
  1169.     if (dlist==0) NotSet(880,9);
  1170.  
  1171.     adr=dlist->dl_AdrB;
  1172.     adr->BitMapTable[0]=881L;
  1173.     adr->BMvalid=-1;
  1174.  
  1175.     /*printf("GFree: %d DFree: %d\n",GFree,DFree);*/
  1176.  
  1177.     for (n=0;n!=56;n++) buffbm[n]=-1L;    /* on nettoye le BitMap */
  1178.     for (n=56;n!=128;n++) buffbm[n]=0L;
  1179.     if (DFree<880)
  1180.     {
  1181.         for (n=0;n<DFree;n++) SetBinBM(n,buffbm);
  1182.     }
  1183.     else
  1184.     {
  1185.         for (n=0;n!=880;n++) SetBinBM(n,buffbm);
  1186.         for (n=DFree+1;n!=1761;n++) SetBinBM(n,buffbm);
  1187.         
  1188.     }
  1189.  
  1190.     for (n=880;n!=GFree;n++) SetBinBM(n,buffbm);
  1191.  
  1192.     buffbm[0]=0L;
  1193.     for (n=0;n!=128;n++)
  1194.     {
  1195.         SBM+=buffbm[n];
  1196.     }
  1197.     buffbm[0]=-SBM;
  1198.  
  1199. }
  1200.  
  1201. SetBinBM(bloc,adrbm)
  1202. WORD bloc;
  1203. LONG *adrbm;
  1204. {
  1205.     adrbm++;
  1206.     adrbm[(bloc-2)/32] &= ~(1<< ( (bloc-2)%32 ));
  1207. }
  1208.  
  1209. /* Les options. */
  1210.  
  1211. WBench(flag)
  1212. BYTE flag;
  1213. {
  1214.     CLI=!flag;
  1215. /*    printf("in WBench, CLI set to %d\n",!flag);*/
  1216. }
  1217.  
  1218. ComLineInt(flag)
  1219. BYTE flag;
  1220. {
  1221.     CLI=flag;
  1222. /*    printf("in ComLineInt, CLI set to %d\n",flag);*/
  1223. }
  1224.  
  1225. NoFormat(flag)
  1226. BYTE flag;
  1227. {
  1228.     VarAdr->Format=!flag;
  1229. /*    printf("in NoFormat, Format set to %d\n",VarAdr->Format);*/
  1230. }
  1231.  
  1232. forFDir(flag)
  1233. BYTE flag;
  1234. {
  1235.     FLnog=flag;
  1236. /*     printf("in forFDir, FLnog set to %d\n",flag);*/
  1237. }
  1238.  
  1239. Check(flag)
  1240. BYTE flag;
  1241. {
  1242.     CHECK=flag;
  1243. }
  1244.  
  1245. help()
  1246. {
  1247.     puts("FO is FreeWare but contributions are welcomed: ");
  1248.     puts("");
  1249.     puts("Send any donations to CAMPAGNE Fabien");
  1250.     puts("                      805,  Rue des Gentianes");
  1251.     puts("                      39000 Lons Le Saunier");
  1252.     puts("                      France");
  1253.     puts("");
  1254.     puts("Now how to use FO:");
  1255.     puts("          1st argument must be SOURCE drive");
  1256.     puts("          2nd argument must be DESTINATION drive");
  1257.     puts("                        (They could be the same)");
  1258.     puts("Options:");
  1259.     puts("          -w : Worbench optimization ( all .info files (ex disk.info) are");
  1260.     puts("                near gestion-blocks)");
  1261.     puts("          -c : CLI optimization ( .info files are in the area of data-blocks)");
  1262.     puts("          -nFo or -nFormat if you use disk already formatted on destination.");
  1263.     puts("          -C : Check of the Dos Structure of Source disk before optimization.");
  1264.     puts("          -FDir : to use in conjunction with FDir (the Fast Dir by mine)");
  1265.     puts("                  (File List blocks are moved in data-area)");
  1266.     puts("");
  1267.     puts("                                 Enjoy FO.           FBJ.");
  1268. }
  1269.  
  1270.  
  1271.  
  1272.  
  1273.  
  1274.  
  1275.  
  1276.  
  1277.